﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;

namespace BizElements.TemplateEngine
{
    /// <summary>Provides common operation for text manipulation.</summary>
    internal static class TextUtil
    {
        #region CountLines.

        /// <summary>Counts the number of lines in given text.</summary>
        public static int CountLines(string text)
        {
            int lineCount = 0;
            using (StringReader reader = new StringReader(text))
            {
                while (null != reader.ReadLine())
                    lineCount++;
            }

            return lineCount;
        }

        #endregion

        #region Trim.

        /// <summary>Trims string.</summary>
        public static string Trim(string text)
        {
            return (text != null) ? text.Trim() : "";
        }

        #endregion
    }

    /// <summary>Represents input text with parsed lines.</summary>
    internal sealed class TextLines
    {
        /// <summary>Gets all text including line breaks.</summary>
        public string Text { get; private set; }
        
        /// <summary>Text broken into lines.</summary>
        public string[] Lines { get; private set; }

        private TextLines()
        {
        }

        /// <summary>Reads text and parses it into lines.</summary>
        public static TextLines Read(Stream input)
        {
            StringBuilder text = new StringBuilder();
            List<string> lines = new List<string>();
            string currLine;
            using (StreamReader reader = new StreamReader(input))
            {
                while (reader.Peek() >= 0)
                {
                    currLine = reader.ReadLine();
                    text.AppendLine(currLine);
                    lines.Add(currLine);
                }
            }

            TextLines textLines = new TextLines()
            {
                Text = text.ToString(),
                Lines = lines.ToArray()
            };
            return textLines;
        }

        private int[] GetLineAndColumnNumberOfFirstOccurence(string linePart)
        {
            for (int lineIdx = 0; lineIdx < this.Lines.Length; lineIdx++)
            {
                int colIdx = this.Lines[lineIdx].IndexOf(linePart, StringComparison.CurrentCulture);
                bool isFound = (colIdx >= 0);
                if (isFound)
                {
                    int lineNumber = lineIdx + 1;
                    int colNumber = colIdx + 1;
                    return new int[] { lineNumber, colNumber };
                }
            }

            return null;
        }

        /// <summary>Gets first entire line that contains the specified part.</summary>
        public string GetLineWithText(string linePart)
        {
            int[] lineAndCol = GetLineAndColumnNumberOfFirstOccurence(linePart);
            if (lineAndCol == null)
                return null;

            int lineIdx = lineAndCol[0] - 1;
            string line = (lineAndCol != null) ? this.Lines[lineIdx] : null;
            return line;
        }
    }
}
